From 7b9ace488b01e4f2d68e9c06659f8eed4a9b76ca Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 17 Dec 2016 04:22:44 +0100 Subject: [PATCH] vulkan: Add GskVulkanUploader It's the thing that makes sure pixels end up on the GPU. --- gsk/gskvulkanimage.c | 121 ++++++++++++++++++++----------- gsk/gskvulkanimageprivate.h | 11 ++- gsk/gskvulkanrender.c | 9 ++- gsk/gskvulkanrenderer.c | 9 +-- gsk/gskvulkanrendererprivate.h | 2 +- gsk/gskvulkanrenderpass.c | 14 ++-- gsk/gskvulkanrenderpassprivate.h | 2 +- 7 files changed, 108 insertions(+), 60 deletions(-) diff --git a/gsk/gskvulkanimage.c b/gsk/gskvulkanimage.c index f65b021fe4..e0550e73cb 100644 --- a/gsk/gskvulkanimage.c +++ b/gsk/gskvulkanimage.c @@ -8,6 +8,16 @@ #include +struct _GskVulkanUploader +{ + GdkVulkanContext *vulkan; + + GskVulkanCommandPool *command_pool; + + GSList *staging_image_free_list; + GSList *staging_buffer_free_list; +}; + struct _GskVulkanImage { GObject parent_instance; @@ -24,6 +34,39 @@ struct _GskVulkanImage G_DEFINE_TYPE (GskVulkanImage, gsk_vulkan_image, G_TYPE_OBJECT) +GskVulkanUploader * +gsk_vulkan_uploader_new (GdkVulkanContext *context, + GskVulkanCommandPool *command_pool) +{ + GskVulkanUploader *self; + + self = g_slice_new0 (GskVulkanUploader); + + self->vulkan = g_object_ref (context); + self->command_pool = command_pool; + + return self; +} + +void +gsk_vulkan_uploader_free (GskVulkanUploader *self) +{ + gsk_vulkan_uploader_reset (self); + + g_object_unref (self->vulkan); + + g_slice_free (GskVulkanUploader, self); +} + +void +gsk_vulkan_uploader_reset (GskVulkanUploader *self) +{ + g_slist_free_full (self->staging_image_free_list, g_object_unref); + self->staging_image_free_list = NULL; + g_slist_free_full (self->staging_buffer_free_list, (GDestroyNotify) gsk_vulkan_buffer_free); + self->staging_buffer_free_list = NULL; +} + static GskVulkanImage * gsk_vulkan_image_new (GdkVulkanContext *context, gsize width, @@ -139,19 +182,18 @@ gsk_vulkan_image_ensure_view (GskVulkanImage *self, } GskVulkanImage * -gsk_vulkan_image_new_from_data_via_staging_buffer (GdkVulkanContext *context, - GskVulkanCommandPool *command_pool, - guchar *data, - gsize width, - gsize height, - gsize stride) +gsk_vulkan_image_new_from_data_via_staging_buffer (GskVulkanUploader *uploader, + guchar *data, + gsize width, + gsize height, + gsize stride) { GskVulkanImage *self; GskVulkanBuffer *staging; VkCommandBuffer command_buffer; guchar *mem; - staging = gsk_vulkan_buffer_new_staging (context, width * height * 4); + staging = gsk_vulkan_buffer_new_staging (uploader->vulkan, width * height * 4); mem = gsk_vulkan_buffer_map (staging); if (stride == width * 4) @@ -168,14 +210,14 @@ gsk_vulkan_image_new_from_data_via_staging_buffer (GdkVulkanContext *context gsk_vulkan_buffer_unmap (staging); - self = gsk_vulkan_image_new (context, + self = gsk_vulkan_image_new (uploader->vulkan, width, height, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - command_buffer = gsk_vulkan_command_pool_get_buffer (command_pool); + command_buffer = gsk_vulkan_command_pool_get_buffer (uploader->command_pool); vkCmdPipelineBarrier (command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, @@ -252,10 +294,9 @@ gsk_vulkan_image_new_from_data_via_staging_buffer (GdkVulkanContext *context } }); - gsk_vulkan_command_pool_submit_buffer (command_pool, command_buffer, VK_NULL_HANDLE); + gsk_vulkan_command_pool_submit_buffer (uploader->command_pool, command_buffer, VK_NULL_HANDLE); - /* XXX: Is this okay or do we need to keep the staging image around until the commands execute */ - gsk_vulkan_buffer_free (staging); + uploader->staging_buffer_free_list = g_slist_prepend (uploader->staging_buffer_free_list, staging); gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_SRGB); @@ -263,17 +304,16 @@ gsk_vulkan_image_new_from_data_via_staging_buffer (GdkVulkanContext *context } GskVulkanImage * -gsk_vulkan_image_new_from_data_via_staging_image (GdkVulkanContext *context, - GskVulkanCommandPool *command_pool, - guchar *data, - gsize width, - gsize height, - gsize stride) +gsk_vulkan_image_new_from_data_via_staging_image (GskVulkanUploader *uploader, + guchar *data, + gsize width, + gsize height, + gsize stride) { GskVulkanImage *self, *staging; VkCommandBuffer command_buffer; - staging = gsk_vulkan_image_new (context, + staging = gsk_vulkan_image_new (uploader->vulkan, width, height, VK_IMAGE_TILING_LINEAR, @@ -282,14 +322,14 @@ gsk_vulkan_image_new_from_data_via_staging_image (GdkVulkanContext *context, gsk_vulkan_image_upload_data (staging, data, width, height, stride); - self = gsk_vulkan_image_new (context, + self = gsk_vulkan_image_new (uploader->vulkan, width, height, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - command_buffer = gsk_vulkan_command_pool_get_buffer (command_pool); + command_buffer = gsk_vulkan_command_pool_get_buffer (uploader->command_pool); vkCmdPipelineBarrier (command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, @@ -388,10 +428,9 @@ gsk_vulkan_image_new_from_data_via_staging_image (GdkVulkanContext *context, } }); - gsk_vulkan_command_pool_submit_buffer (command_pool, command_buffer, VK_NULL_HANDLE); + gsk_vulkan_command_pool_submit_buffer (uploader->command_pool, command_buffer, VK_NULL_HANDLE); - /* XXX: Is this okay or do we need to keep the staging image around until the commands execute */ - g_object_unref (staging); + uploader->staging_image_free_list = g_slist_prepend (uploader->staging_image_free_list, staging); gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_SRGB); @@ -399,19 +438,18 @@ gsk_vulkan_image_new_from_data_via_staging_image (GdkVulkanContext *context, } GskVulkanImage * -gsk_vulkan_image_new_from_data_directly (GdkVulkanContext *context, - GskVulkanCommandPool *command_pool, - guchar *data, - gsize width, - gsize height, - gsize stride) +gsk_vulkan_image_new_from_data_directly (GskVulkanUploader *uploader, + guchar *data, + gsize width, + gsize height, + gsize stride) { VkCommandBuffer command_buffer; GskVulkanImage *self; - command_buffer = gsk_vulkan_command_pool_get_buffer (command_pool); + command_buffer = gsk_vulkan_command_pool_get_buffer (uploader->command_pool); - self = gsk_vulkan_image_new (context, + self = gsk_vulkan_image_new (uploader->vulkan, width, height, VK_IMAGE_TILING_LINEAR, @@ -446,7 +484,7 @@ gsk_vulkan_image_new_from_data_directly (GdkVulkanContext *context, } }); - gsk_vulkan_command_pool_submit_buffer (command_pool, command_buffer, VK_NULL_HANDLE); + gsk_vulkan_command_pool_submit_buffer (uploader->command_pool, command_buffer, VK_NULL_HANDLE); gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_SRGB); @@ -454,19 +492,18 @@ gsk_vulkan_image_new_from_data_directly (GdkVulkanContext *context, } GskVulkanImage * -gsk_vulkan_image_new_from_data (GdkVulkanContext *context, - GskVulkanCommandPool *command_pool, - guchar *data, - gsize width, - gsize height, - gsize stride) +gsk_vulkan_image_new_from_data (GskVulkanUploader *uploader, + guchar *data, + gsize width, + gsize height, + gsize stride) { if (GSK_RENDER_MODE_CHECK (STAGING_BUFFER)) - return gsk_vulkan_image_new_from_data_via_staging_buffer (context, command_pool, data, width, height, stride); + return gsk_vulkan_image_new_from_data_via_staging_buffer (uploader, data, width, height, stride); if (GSK_RENDER_MODE_CHECK (STAGING_IMAGE)) - return gsk_vulkan_image_new_from_data_via_staging_image (context, command_pool, data, width, height, stride); + return gsk_vulkan_image_new_from_data_via_staging_image (uploader, data, width, height, stride); else - return gsk_vulkan_image_new_from_data_directly (context, command_pool, data, width, height, stride); + return gsk_vulkan_image_new_from_data_directly (uploader, data, width, height, stride); } GskVulkanImage * diff --git a/gsk/gskvulkanimageprivate.h b/gsk/gskvulkanimageprivate.h index 3d6668e347..e146ce7cf6 100644 --- a/gsk/gskvulkanimageprivate.h +++ b/gsk/gskvulkanimageprivate.h @@ -7,17 +7,24 @@ G_BEGIN_DECLS +typedef struct _GskVulkanUploader GskVulkanUploader; + #define GSK_TYPE_VULKAN_IMAGE (gsk_vulkan_image_get_type ()) G_DECLARE_FINAL_TYPE (GskVulkanImage, gsk_vulkan_image, GSK, VULKAN_IMAGE, GObject) +GskVulkanUploader * gsk_vulkan_uploader_new (GdkVulkanContext *context, + GskVulkanCommandPool *command_pool); +void gsk_vulkan_uploader_free (GskVulkanUploader *self); + +void gsk_vulkan_uploader_reset (GskVulkanUploader *self); + GskVulkanImage * gsk_vulkan_image_new_for_swapchain (GdkVulkanContext *context, VkImage image, VkFormat format, gsize width, gsize height); -GskVulkanImage * gsk_vulkan_image_new_from_data (GdkVulkanContext *context, - GskVulkanCommandPool *pool, +GskVulkanImage * gsk_vulkan_image_new_from_data (GskVulkanUploader *uploader, guchar *data, gsize width, gsize height, diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c index dffd20d256..4d0f5f715a 100644 --- a/gsk/gskvulkanrender.c +++ b/gsk/gskvulkanrender.c @@ -29,6 +29,7 @@ struct _GskVulkanRender VkFence fence; VkRenderPass render_pass; GskVulkanPipelineLayout *layout; + GskVulkanUploader *uploader; GHashTable *descriptor_set_indexes; VkDescriptorPool descriptor_pool; @@ -155,6 +156,8 @@ gsk_vulkan_render_new (GskRenderer *renderer, self->layout = gsk_vulkan_pipeline_layout_new (self->vulkan); + self->uploader = gsk_vulkan_uploader_new (self->vulkan, self->command_pool); + return self; } @@ -235,7 +238,7 @@ gsk_vulkan_render_upload (GskVulkanRender *self) for (l = self->render_passes; l; l = l->next) { - gsk_vulkan_render_pass_upload (l->data, self, self->command_pool); + gsk_vulkan_render_pass_upload (l->data, self, self->uploader); } } @@ -515,6 +518,8 @@ gsk_vulkan_render_cleanup (GskVulkanRender *self) 1, &self->fence); + gsk_vulkan_uploader_reset (self->uploader); + gsk_vulkan_command_pool_reset (self->command_pool); g_hash_table_remove_all (self->descriptor_set_indexes); @@ -556,6 +561,8 @@ gsk_vulkan_render_free (GskVulkanRender *self) for (i = 0; i < GSK_VULKAN_N_PIPELINES; i++) g_clear_object (&self->pipelines[i]); + g_clear_pointer (&self->uploader, gsk_vulkan_uploader_free); + g_clear_pointer (&self->layout, gsk_vulkan_pipeline_layout_unref); vkDestroyRenderPass (device, diff --git a/gsk/gskvulkanrenderer.c b/gsk/gskvulkanrenderer.c index cf550b3fea..3cab29fd4a 100644 --- a/gsk/gskvulkanrenderer.c +++ b/gsk/gskvulkanrenderer.c @@ -269,9 +269,9 @@ gsk_vulkan_renderer_clear_texture (gpointer p) } GskVulkanImage * -gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self, - GskTexture *texture, - GskVulkanCommandPool *command_pool) +gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self, + GskTexture *texture, + GskVulkanUploader *uploader) { GskVulkanTextureData *data; cairo_surface_t *surface; @@ -282,8 +282,7 @@ gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self, return g_object_ref (data->image); surface = gsk_texture_download (texture); - image = gsk_vulkan_image_new_from_data (self->vulkan, - command_pool, + image = gsk_vulkan_image_new_from_data (uploader, cairo_image_surface_get_data (surface), cairo_image_surface_get_width (surface), cairo_image_surface_get_height (surface), diff --git a/gsk/gskvulkanrendererprivate.h b/gsk/gskvulkanrendererprivate.h index 982983a777..5794ba1d53 100644 --- a/gsk/gskvulkanrendererprivate.h +++ b/gsk/gskvulkanrendererprivate.h @@ -23,7 +23,7 @@ GType gsk_vulkan_renderer_get_type (void) G_GNUC_CONST; GskVulkanImage * gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self, GskTexture *texture, - GskVulkanCommandPool *command_pool); + GskVulkanUploader *uploader); G_END_DECLS diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c index 6e1461c5df..5290d0e600 100644 --- a/gsk/gskvulkanrenderpass.c +++ b/gsk/gskvulkanrenderpass.c @@ -176,7 +176,7 @@ static void gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderPass *self, GskVulkanOpRender *op, GskVulkanRender *render, - GskVulkanCommandPool *command_pool) + GskVulkanUploader *uploader) { graphene_rect_t bounds; cairo_surface_t *surface; @@ -194,8 +194,7 @@ gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderPass *self, cairo_destroy (cr); - op->source = gsk_vulkan_image_new_from_data (self->vulkan, - command_pool, + op->source = gsk_vulkan_image_new_from_data (uploader, cairo_image_surface_get_data (surface), cairo_image_surface_get_width (surface), cairo_image_surface_get_height (surface), @@ -209,7 +208,7 @@ gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderPass *self, void gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self, GskVulkanRender *render, - GskVulkanCommandPool *command_pool) + GskVulkanUploader *uploader) { GskVulkanOp *op; guint i; @@ -221,14 +220,13 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self, switch (op->type) { case GSK_VULKAN_OP_FALLBACK: - gsk_vulkan_render_pass_upload_fallback (self, &op->render, render, command_pool); + gsk_vulkan_render_pass_upload_fallback (self, &op->render, render, uploader); break; case GSK_VULKAN_OP_SURFACE: { cairo_surface_t *surface = gsk_cairo_node_get_surface (op->render.node); - op->render.source = gsk_vulkan_image_new_from_data (self->vulkan, - command_pool, + op->render.source = gsk_vulkan_image_new_from_data (uploader, cairo_image_surface_get_data (surface), cairo_image_surface_get_width (surface), cairo_image_surface_get_height (surface), @@ -241,7 +239,7 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self, { op->render.source = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)), gsk_texture_node_get_texture (op->render.node), - command_pool); + uploader); gsk_vulkan_render_add_cleanup_image (render, op->render.source); } break; diff --git a/gsk/gskvulkanrenderpassprivate.h b/gsk/gskvulkanrenderpassprivate.h index 7d5478dabc..fa012798b0 100644 --- a/gsk/gskvulkanrenderpassprivate.h +++ b/gsk/gskvulkanrenderpassprivate.h @@ -21,7 +21,7 @@ void gsk_vulkan_render_pass_add (GskVulk void gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self, GskVulkanRender *render, - GskVulkanCommandPool *command_pool); + GskVulkanUploader *uploader); gsize gsk_vulkan_render_pass_count_vertices (GskVulkanRenderPass *self); gsize gsk_vulkan_render_pass_collect_vertices (GskVulkanRenderPass *self, -- 2.30.2